//
//  AppTool.swift
//  TestAPIManager
//
//  Created by yq on 2020/10/14.
//  Copyright © 2020 杨庆. All rights reserved.
//

import Foundation
import UIKit



//protocol YReuseable {}
//extension YReuseable where Self:UIView {
//    static var reuseIdentifier:String {
//        return String(describing: self)
//    }
//}

protocol XReusable {}
extension XReusable where Self:UIView {
    static var reuseIdentifier:String {
        return String(describing: self)
    }
}

protocol Ynibloadable {}

extension Ynibloadable {
    static var nibName:String {
        return String(describing:self)
    }
    static var loadfromNib:Self {
        return Bundle.main.loadNibNamed(nibName, owner: nil, options: nil)?.last as! Self
    }
}


protocol XNibLoadable {}
extension XNibLoadable where Self:UIView {
    static var nibName:String {
        return String(describing:self)
    }
    static var loadFromNib:Self {
        return Bundle.main.loadNibNamed(nibName, owner: nil, options: nil)?.last as! Self
    }
}


protocol NibLoadable {}
extension NibLoadable where Self:UIView {
    static var nibName:String {
        return String(describing:self)
    }
    static var loadFromNib:Self {
        return Bundle.main.loadNibNamed(nibName, owner: nil, options: nil)?.last as! Self
    }
}


protocol Yidentifier {}
extension Yidentifier where Self:UIView {
    static var reuserableIdentifier:String {
        return String(describing: self)
    }
}

protocol YNibLoadable {}
extension YNibLoadable where Self:UIView {
    static var nibName:String {
        return String(describing:self)
    }
    static var loadFromNib:Self {
       return  Bundle.main.loadNibNamed(nibName, owner: nil , options: nil)?.last as! Self
    }
}


extension UITableView {

    func register<T:UITableViewCell>(_:T.Type) where T:Yidentifier {
        register(T.self, forCellReuseIdentifier: T.reuserableIdentifier)
    }
    
    func regist<T:UITableViewCell>(_ : T.Type) where T:YNibLoadable&Yidentifier {
        let nib = UINib.init(nibName: T.nibName, bundle: nil)
        register(nib, forCellReuseIdentifier: T.reuserableIdentifier)
    }
}



extension UITableView {
    
    func dequeueReusableCell<T:UITableViewCell>(from _:T.Type, indexPath:IndexPath)->T where T:Yidentifier {
        return dequeueReusableCell(withIdentifier: T.reuserableIdentifier, for: indexPath) as! T
    }
}



import UIKit

// MARK: - 注册
extension UITableView {
    
    /// 通过 Class 注册 cell
    ///
    /// - Parameter _: 遵循 ReusableView 协议
    func register<T: UITableViewCell>(_: T.Type) where T: XReusable {
        register(T.self, forCellReuseIdentifier: T.reuseIdentifier)
    }
    
    /// 通过 nib 注册 cell
    ///
    /// - Parameter _: 遵循 ReusableView 和 NibLoadableView 协议
    func register<T: UITableViewCell>(_: T.Type) where T: XReusable & XNibLoadable {
        let cellNib = UINib(nibName: T.nibName, bundle: nil)
        register(cellNib, forCellReuseIdentifier: T.reuseIdentifier)
    }
    
    /// 通过 Class 注册 headerFooterView
    ///
    /// - Parameter _: 遵循 ReusableView 协议
    func register<T: UITableViewHeaderFooterView>(_: T.Type) where T: XReusable {
        register(T.self, forHeaderFooterViewReuseIdentifier: T.reuseIdentifier)
    }
}

// MARK: - 从缓存池中取出
extension UITableView {
    /// 从缓存池中取出 cell
    ///
    /// - Parameters:
    ///   - _: 遵循 ReusableView 协议
    ///   - indexPath: IndexPath
    /// - Returns: cell
    func dequeueReusableCell<T: UITableViewCell>(_: T.Type, for indexPath: IndexPath) -> T where T: XReusable {
        guard let cell = dequeueReusableCell(withIdentifier: T.reuseIdentifier, for: indexPath) as? T else {
            fatalError("Could not dequeue cell with identifier : \(T.reuseIdentifier)")
        }
        return cell
    }
    
    /// 从缓存池中取出 headerFooterView
    ///
    /// - Parameter _: 遵循 ReusableView 协议
    /// - Returns: headerFooterView
    func dequeueReusableHeaderFooterView<T: UITableViewHeaderFooterView>(_: T.Type) -> T where T: XReusable {
        guard let headerFooterView = dequeueReusableHeaderFooterView(withIdentifier: T.reuseIdentifier) as? T else {
            fatalError("Could not dequeue reusable header footer view with identifier : \(T.reuseIdentifier)")
        }
        return headerFooterView
    }
    
    
    
    
}
